from utils import debug_info
import gc


class TCPServer:
	def __init__(self):
		import socket
		from config import Config

		host = socket.getaddrinfo('0.0.0.0', Config.TCP_PORT)[0][-1]

		self._server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self._server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		self._server.bind(host)
		self._server.listen(1)

		debug_info("tcp server bind on port %s" % Config.TCP_PORT)

	def start(self):
		from utime import sleep_ms

		while True:
			sleep_ms(300)

			client, address = self._server.accept()

			debug_info("client[%s:%s] connected" % address)

			request = str(client.recv(1024), "utf-8").strip()

			if len(request) == 0:
				client.close()
				debug_info("client[%s:%s] disconnected" % address)

				continue

			debug_info("received tcp request: %s [%s:%s]" % (request, address[0], address[1]))

			# process client request(control command)
			self._respond_to_client(client, request)
			client.close()

			gc.collect()

	@staticmethod
	def _respond_to_client(client, request: str):
		from wifihandler import WifiHandler
		from webservice.commands import Commands
		from utils import save_information, hard_reset
		from utime import sleep_ms

		if request.startswith(Commands.QUERY_PREFIX):
			command = Commands.get_command(request)

			# analyse request command
			# and analyse params based on command
			if command == Commands.CMD_SETUP_STATION:
				if type(Commands.get_params(request)) is not bool:
					essid, password = Commands.get_params(request)

					# try to connect via station mode
					result_code = WifiHandler.set_sta_mode(essid, password)

					if result_code == 5:
						# success, return station mode mac address
						respond_msg = Commands.RESULT_SETUP_STATION_SUCCESS % WifiHandler.get_mac_address(WifiHandler.STA_MODE)

						client.send(bytes(respond_msg, "utf-8"))

						# save essid & password into local file
						# and hard reset board
						if save_information(essid, password):
							sleep_ms(1000)

							hard_reset()
						else:
							raise IOError("save information file failed")
					else:
						# connection failed
						respond_msg = Commands.RESULT_SETUP_STATION_FAILED
				else:
					# invalid params
					respond_msg = Commands.RESULT_INVALID_PARAMS
			else:
				# invalid command
				respond_msg = Commands.RESULT_INVALID_COMMAND
		else:
			respond_msg = Commands.RESULT_INVALID_COMMAND

		gc.collect()

		client.send(bytes(respond_msg, "utf-8"))
